home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / fly8111-.000 / fly8111- / fly8 / memory1.c < prev    next >
C/C++ Source or Header  |  1979-12-31  |  14KB  |  691 lines

  1. /* --------------------------------- memory.c ------------------------------- */
  2.  
  3. /* This is part of the flight simulator 'fly8'.
  4.  * Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
  5. */
  6.  
  7. /* A general purpose memory manager.
  8.  *
  9.  * This one keeps no extra information on allocated blocks. Free blocks
  10.  * are linked by size and address to allow fast access for both allocation
  11.  * and freeing/merging of blocks. It needs to have the block size suppplied
  12.  * in the free() call, so watch out if you STRdup() and then modify the 
  13.  * string since it will confuse it.
  14.  *
  15.  * It uses less memory than the faster manager used now with Fly8. Only
  16.  * one fixed table of 256 entries of BLOCKS (3 pointers each). So the usage
  17.  * is fixed a 3kb.
  18. */
  19.  
  20. #include "fly.h"
  21.  
  22.  
  23. #define SIZES        0
  24. #define HEADS        1
  25. #define TAILS        2
  26.  
  27. #define GRAIN        8
  28.  
  29. #define NBLOCKS        256
  30.  
  31. #define MAXBYTES    (NBLOCKS*GRAIN)
  32.  
  33. #define MINBYTES \
  34.     (offsetof (BLOCK, size) + sizeof (((BLOCK *)NULL)->size))
  35.  
  36. #define CHUNKSIZE    (MAXBYTES*4)
  37.  
  38. #define CHUNKMIN    (CHUNKSIZE/4)
  39.  
  40. #define CHUNKPART    (CHUNKMIN/2)
  41.  
  42. #define BYTESINDEX(n) \
  43.     ((Uint)(((n) < MINBYTES ? MINBYTES : (n)) - 1) / GRAIN)
  44.  
  45. #define INDEXSIZE(i)    (((i) + 1) * GRAIN)
  46.  
  47. #define ROUNDBYTES(n)    INDEXSIZE (BYTESINDEX (n))
  48.  
  49. #define PTRINDEX(p) \
  50.     (Uint)((13579UL * ((Uint)(p) ^ (Uint)((Ulong)(p) >> 16))) % NBLOCKS)
  51.  
  52. #define LISTREMOVE(b,list) \
  53.     do { \
  54.         if (T(b->prev[list]->next[list] = b->next[list])) \
  55.             b->next[list]->prev[list] = b->prev[list]; \
  56.     } while (0)
  57.  
  58. #define LISTADD(b,list,n) \
  59.     do { \
  60.         b->prev[list] = (BLOCK *)&blocks[n]; \
  61.         if (T(b->next[list] = blocks[n].next[list])) \
  62.             b->next[list]->prev[list] = b; \
  63.         blocks[n].next[list] = b; \
  64.     } while (0)
  65.  
  66. #define MEM_MINLOG    MAXBYTES+1        /* log nothing */
  67.  
  68. /* Each block has three doubly-linked lists and a size. Note that we cheat
  69.  * and expect the next[3] array in BLOCKS to be used in place of the similar
  70.  * field in BLOCK (see the cast above in LISTADD).
  71. */
  72. typedef struct block    BLOCK;
  73. struct block {
  74.     BLOCK    *next[3];
  75.     BLOCK    *prev[3];
  76.     Ushort    size;
  77. };
  78.  
  79. /* Free blocks are kept on a cached list.
  80. */
  81. typedef struct blocks    BLOCKS;
  82. struct blocks {
  83.     BLOCK    *next[3];        /* MUST be same as BLOCK start */
  84. #ifdef MEM_STATS
  85.     short    nused;                /* stats: good alloc - free */
  86.     Ulong    nalloc;                /* stats: requested alloc */
  87.     Ulong    nomem;                /* stats: memory short count */
  88. #endif
  89. };
  90.  
  91. /* memory is acquired in large chunks to later be carved into allocated
  92.  * blocks.
  93. */
  94. typedef struct chunk    CHUNK;
  95. struct chunk {
  96.     CHUNK    *next;
  97.     Uint    avail;                /* size  of free space */
  98.     Uchar    *mem;                /* start of free space */
  99.     Uchar    buff[CHUNKSIZE];
  100. };
  101.  
  102. static BLOCKS    *blocks = 0;
  103. static CHUNK    *chunks = 0;
  104. static Uint    malloc_dead = 0;        /* malloc failed! */
  105. static Uint    largestAvail = 0;
  106. static Ulong    ngrains = 0;            /* stats total malloc size */
  107. static Ulong    nReqs = 0;            /* stats: block free requests */
  108. static Ulong    nProbes = 0;            /* stats: block search length */
  109. static int    debugging = 0;
  110. static int    logging = 0;
  111.  
  112. LOCAL_FUNC void NEAR
  113. mem_assert (void)
  114. {
  115.     int    i, n;
  116.     BLOCK    *p;
  117.     long    totbytes = 0;
  118.  
  119.     totbytes = STATS_MEMALLOCED;
  120.     for (i = 0; i < NBLOCKS; ++i) {
  121.         n = INDEXSIZE (i);
  122.         for (p = blocks[i].next[SIZES]; p; p = p->next[SIZES]) {
  123.             if (p->size !=  (Uint)n)
  124.                 LogPrintf ("assert: Bad size %5d in list %d\n",
  125.                     p->size, n);
  126.             totbytes += n;
  127.         }
  128.     }
  129.     if (T(totbytes -= ngrains*GRAIN))
  130.         LogPrintf ("assert: leakage %9ld\n", -totbytes);
  131. }
  132.  
  133. /* A set of safe memory management functions.
  134. */
  135.  
  136. extern void * FAR
  137. xmalloc (Uint size)
  138. {
  139.     Ulong    flags;
  140.     void    *p;
  141.  
  142.     if (!malloc_dead) {
  143.         flags = Sys->Disable ();
  144.         if (F(p = malloc (size))) {
  145.             malloc_dead = 1;
  146.             ++STATS_MEMLOW;
  147.         }
  148.         Sys->Enable (flags);
  149.     } else {
  150.         ++STATS_MEMLOW;
  151.         p = NULL;
  152.     }
  153.     return (p);
  154. }
  155.  
  156. extern void * FAR
  157. xcalloc (Uint count, Uint size)
  158. {
  159.     Ulong    flags;
  160.     void    *p;
  161.  
  162.     if (!malloc_dead) {
  163.         flags = Sys->Disable ();
  164.         if (F(p = calloc (count, size))) {
  165.             malloc_dead = 1;
  166.             ++STATS_MEMLOW;
  167.         }
  168.         Sys->Enable (flags);
  169.     } else {
  170.         ++STATS_MEMLOW;
  171.         p = NULL;
  172.     }
  173.     return (p);
  174. }
  175.  
  176. extern char * FAR
  177. xstrdup (const char *s)
  178. {
  179.     char    *p;
  180.     Ulong    flags;
  181.  
  182.     flags = Sys->Disable ();
  183.     if (F(p = strdup (s))) {
  184.         malloc_dead = 1;
  185.         ++STATS_MEMLOW;
  186.     }
  187.     Sys->Enable (flags);
  188.     return (p);
  189. }
  190.  
  191. extern void * FAR
  192. xfree (void *block)
  193. {
  194.     Ulong    flags;
  195.  
  196.     if (!block)
  197.         return (0);
  198.  
  199.     flags = Sys->Disable ();
  200.     free (block);
  201.     Sys->Enable (flags);
  202.     malloc_dead = 0;
  203.     return (0);
  204. }
  205.  
  206. /* We get here if the free blocks list cannot satisfy a memory allocation
  207.  * request.
  208. */
  209. LOCAL_FUNC void * NEAR
  210. my_alloc (Uint bytes)
  211. {
  212.     CHUNK    *p, *c;
  213.     void    *b;
  214.     int    n;
  215.  
  216.     p = NULL;
  217.     if (largestAvail >= (Ushort)bytes) {
  218.         for (c = chunks; c; c = c->next) {
  219.             if (c->avail >= bytes && (NULL == p
  220.                           || p->avail > c->avail))
  221.                 p = c;
  222.         }
  223.     }
  224.     if (F(p)) {
  225.         if (!malloc_dead) {
  226.             for (n = sizeof (*p); n > CHUNKMIN; n -= CHUNKPART) {
  227.                 if (T(p = (CHUNK *)malloc (n)))
  228.                     break;
  229.             }
  230.         }
  231.         if (F(p)) {
  232.             malloc_dead = 1;
  233.             ++STATS_MEMLOW;
  234.         } else {
  235.             p->next = chunks;
  236.             chunks = p;
  237.             p->avail = sizeof (p->buff) - (sizeof (*p) - n);
  238.             p->mem = p->buff;
  239.             if (p->avail > largestAvail)
  240.                 largestAvail = p->avail;
  241.             if (p->avail < bytes)
  242.                 p = NULL;
  243.         }
  244.     }
  245.     if (p) {
  246.         b = p->mem;
  247.         p->mem += bytes;
  248.         p->avail -= bytes;
  249.         largestAvail = p->avail;
  250.         for (c = chunks; c; c = c->next) {
  251.             if (c->avail > largestAvail)
  252.                 largestAvail = c->avail;
  253.         }
  254.     } else
  255.         b = NULL;
  256.     return (b);
  257. }
  258.  
  259. /* Try to satisfy a memory request by splitting a larger size block from
  260.  * the free memory list.
  261. */
  262. LOCAL_FUNC BLOCK * NEAR
  263. mem_split (Uint n)
  264. {
  265.     Uint    i;
  266.     Uint    bytes;
  267.     BLOCK    *p;
  268.     BLOCK    *t;
  269.  
  270.     p = NULL;
  271.     for (i = n + 1 + BYTESINDEX (MINBYTES); ++i < NBLOCKS;) {
  272.         if (F(p = blocks[i].next[SIZES]))
  273.             continue;
  274.  
  275.         t = p;                    /* retained block */
  276.  
  277. /* remove p from all lists. heads stays.
  278. */
  279.         LISTREMOVE (t, TAILS);
  280.         LISTREMOVE (t, SIZES);
  281.  
  282.         bytes = INDEXSIZE (n);            /* returned bytes */
  283.         t->size -= bytes;            /* retained bytes */
  284.         p = (BLOCK *)(t->size + (char *)t);    /* returned block */
  285.         i -= n + 1;                /* retained index */
  286.  
  287. /* add the leftover t to all lists.
  288. */
  289.         n = PTRINDEX (p);            /* p is the tail */
  290.         LISTADD (t, TAILS, n);
  291.         LISTADD (t, SIZES, i);
  292.  
  293.         if (logging && debugging && !(st.flags1 & SF_ASYNC))
  294.             LogPrintf ("split %u -> %u + %u\n",
  295.                 p->size, bytes, t->size);
  296.         break;
  297.     }
  298.     return (p);
  299. }
  300.  
  301. extern void * FAR
  302. mem_alloc (Uint bytes)
  303. {
  304.     BLOCK    *p;
  305.     Uint    i;
  306.     Ulong    flags;
  307.  
  308.     if (!bytes || !blocks) {
  309.         p = NULL;
  310.         goto ret;
  311.     }
  312.  
  313.     if (bytes > MAXBYTES) {
  314.         p = xmalloc (bytes);
  315.         goto ret;
  316.     }
  317.  
  318.     i = BYTESINDEX (bytes);
  319.     flags = Sys->Disable ();
  320.  
  321. /* We get memory by first checking for a ready block, then trying to split
  322.  * a larger block, then trying to acquire fresh memory.
  323. */
  324.     if (T(p = blocks[i].next[SIZES])) {
  325.         LISTREMOVE (p, HEADS);
  326.         LISTREMOVE (p, TAILS);
  327.         LISTREMOVE (p, SIZES);
  328.     } else if (T(p = mem_split (i)))
  329.         ++STATS_MEMSPLIT;
  330.     else if (T(p = (BLOCK *)my_alloc (INDEXSIZE (i))))
  331.         STATS_MEMUSED = GRAIN * (ngrains += i + 1);
  332.     else
  333.         ++STATS_MEMNO;
  334.  
  335. #ifdef MEM_STATS
  336.     ++blocks[i].nalloc;
  337.     if (p)
  338.         ++blocks[i].nused;
  339.     else
  340.         ++blocks[i].nomem;
  341. #endif
  342.     if (p)
  343.         STATS_MEMALLOCED += INDEXSIZE (i);
  344.  
  345.     Sys->Enable (flags);
  346. ret:
  347.     if (p)
  348.         memset (p, 0, bytes);
  349.     return ((void *)p);
  350. }
  351.  
  352. extern void * FAR
  353. memd_alloc (Uint bytes, char *file, int lineno)
  354. {
  355.     void    *p;
  356.  
  357.     debugging = 1;
  358.     p = mem_alloc (bytes);
  359.     debugging = 0;
  360.  
  361.     if (logging && !(st.flags1 & SF_ASYNC) && bytes >= MEM_MINLOG)
  362.         LogPrintf ("alloc %s(%d) %u/%p\n", file, lineno, bytes, p);
  363.  
  364.     return (p);
  365. }
  366.  
  367. /* A fast memory manager. A freed block is merged with neighbouring blocks
  368.  * rather than just get added to the pool.
  369. */
  370. extern void * FAR
  371. mem_free (void *bvoid, int bytes)
  372. {
  373.     BLOCK    *b;
  374.     char    *tail;
  375.     BLOCK    *p, *block = (BLOCK *)bvoid;
  376.     int    nheads, ntails, nsizes;
  377.     Uint    maxbytes;
  378.     Ulong    flags;
  379.     int    n;
  380.  
  381.     if (!block || bytes < 0)
  382.         return (NULL);
  383.  
  384.     if (!bytes || bytes > MAXBYTES || !blocks)
  385.         return (xfree (block));
  386.  
  387.     p = block->next[0];        /* for the return(p) */
  388.  
  389.     nsizes  = BYTESINDEX (bytes);
  390.     bytes   = INDEXSIZE (nsizes);
  391.     maxbytes = MAXBYTES - bytes;
  392.  
  393.     flags = Sys->Disable ();
  394.  
  395.     STATS_MEMALLOCED -= bytes;
  396.  
  397. #ifdef MEM_STATS
  398.     --blocks[nsizes].nused;
  399.     if (logging && !(st.flags1 & SF_ASYNC) && blocks[nsizes].nused < 0)
  400.         LogPrintf ("bad free count (%d)\n", bytes);
  401. #else
  402.     if (logging && !(st.flags1 & SF_ASYNC) && STATS_MEMALLOCED < 0)
  403.         LogPrintf ("bad free count (%d)\n", bytes);
  404. #endif
  405.  
  406. /* Search for the head of this block in the tails list.
  407. */
  408.     nheads = PTRINDEX (block);
  409.     tail = bytes + (char *)block;
  410.     ntails = PTRINDEX (tail);
  411. retry:
  412.     for (n = 0, b = blocks[nheads].next[TAILS]; b; b = b->next[TAILS]) {
  413.         ++n;
  414.         if (b->size + (char *)b != (char *)block)
  415.             continue;
  416.         if (b->size > maxbytes)
  417.             break;
  418.  
  419.         if (logging && !(st.flags1 & SF_ASYNC))
  420.             LogPrintf ("mem+ [%5d/%p] + %5d/%p -> %5d/%p\n",
  421.                 b->size, b, bytes, block, b->size+bytes, b);
  422.  
  423.         block = b;
  424.         nheads = PTRINDEX (block);
  425.         goto remove;
  426.     }
  427.     ++nReqs;
  428.     nProbes += n;
  429.  
  430. /* search for the tail of this block in the heads list.
  431. */
  432.     for (n = 0, b = blocks[ntails].next[HEADS]; b; b = b->next[HEADS]) {
  433.         ++n;
  434.         if (tail != (char *)b)
  435.             continue;
  436.         if (b->size > maxbytes)
  437.             break;
  438.  
  439.         if (logging && !(st.flags1 & SF_ASYNC))
  440.             LogPrintf ("mem+ %5d/%p + [%5d/%p] -> %5d/%p\n",
  441.                 bytes, block, b->size, b,
  442.                 b->size+bytes, block);
  443.  
  444.         tail = b->size + (char *)b;
  445.         ntails = PTRINDEX (tail);
  446. remove:
  447.         ++STATS_MEMMERGE;        /* keep stats */
  448.         ++nReqs;
  449.         nProbes += n;
  450.  
  451.         LISTREMOVE (b, HEADS);        /* remove small b */
  452.         LISTREMOVE (b, TAILS);
  453.         LISTREMOVE (b, SIZES);
  454.  
  455.         bytes += b->size;        /* new size */
  456.         nsizes = BYTESINDEX (bytes);
  457.         maxbytes = MAXBYTES - bytes;
  458.         goto retry;
  459.     }
  460.     ++nReqs;
  461.     nProbes += n;
  462.  
  463. /* This is a new block, add it to all lists.
  464. */
  465.     LISTADD (block, HEADS, nheads);
  466.     LISTADD (block, TAILS, ntails);
  467.     LISTADD (block, SIZES, nsizes);
  468.     block->size = (Ushort)bytes;
  469.  
  470.     Sys->Enable (flags);
  471.     return (p);
  472. }
  473.  
  474. extern void * FAR
  475. memd_free (void *block, int bytes, char *file, int lineno)
  476. {
  477.     if (logging && !(st.flags1 & SF_ASYNC) && bytes >= MEM_MINLOG)
  478.         LogPrintf ("free %s(%d) %u/%p\n",
  479.             file, lineno, bytes, block);
  480.  
  481.     return (mem_free (block, bytes));
  482. }
  483.  
  484. extern char * FAR
  485. mem_strdup (const char *s)
  486. {
  487.     char    *p;
  488.     int    len;
  489.  
  490.     if (s) {
  491.         if (T(p = mem_alloc (len = strlen (s) + 1)))
  492.             memcpy (p, s, len);
  493.     } else
  494.         p = NULL;
  495.     return (p);
  496. }
  497.  
  498. extern char * FAR
  499. memd_strdup (const char *s, char *file, int lineno)
  500. {
  501.     char    *p;
  502.     int    len;
  503.  
  504.     if (logging && !(st.flags1 & SF_ASYNC)
  505.                     && (!s || strlen(s)+1 >= MEM_MINLOG))
  506.         LogPrintf ("strdup %s(%d) \"%s\"\n", file, lineno,
  507.             s ? s : "(null)");
  508.  
  509.     if (s) {
  510.         if (T(p = memd_alloc (len = strlen (s) + 1, file, lineno)))
  511.             memcpy (p, s, len);
  512.     } else
  513.         p = NULL;
  514.     return (p);
  515. }
  516.  
  517. extern void * FAR
  518. mem_strfree (char *s)
  519. {
  520.     if (s)
  521.         memory_free (s, strlen (s) + 1);
  522.     return (NULL);
  523. }
  524.  
  525. extern void * FAR
  526. memd_strfree (char *s, char *file, int lineno)
  527. {
  528.     if (logging && !(st.flags1 & SF_ASYNC))
  529.         LogPrintf ("strfree %s(%d) \"%s\"\n", file, lineno,
  530.             s ? s : "(null)");
  531.  
  532.     if (s)
  533.         memd_free (s, strlen (s) + 1, file, lineno);
  534.     return (NULL);
  535. }
  536.  
  537. /* Ensure we are not low on memory. Not yet used.
  538. */
  539. extern void FAR
  540. mem_check (void)
  541. {
  542.     CHUNK    *p, *m;
  543.     Ulong    flags;
  544.  
  545. #if 0
  546.     mem_assert ();
  547. #endif
  548.     if (malloc_dead)
  549.         return;
  550.  
  551.     for (m = p = chunks; p; p = p->next)
  552.         if (p->avail > m->avail)
  553.             m = p;
  554.  
  555.     if (!m || m->avail < CHUNKMIN) {
  556.         flags = Sys->Disable ();
  557.         if (T(p = (CHUNK *)malloc (sizeof (*p)))) {
  558.             p->next = chunks;
  559.             chunks = p;
  560.             p->avail = sizeof (p->buff);
  561.             p->mem = p->buff;
  562.         } else
  563.             malloc_dead = 1;
  564.         Sys->Enable (flags);
  565.     }
  566. }
  567.  
  568. extern int FAR
  569. mem_init (void)
  570. {
  571.     int    i;
  572.  
  573.     ngrains = 0;
  574.     malloc_dead = 0;
  575.     chunks = NULL;
  576.     if (F(blocks = (BLOCKS *)xcalloc (NBLOCKS, sizeof (*blocks))))
  577.         return (1);
  578.  
  579.     for (i = 0; i < NBLOCKS; ++i) {
  580.         blocks[i].next[SIZES] = NULL;
  581.         blocks[i].next[HEADS] = NULL;
  582.         blocks[i].next[TAILS] = NULL;
  583. #ifdef MEM_STATS
  584.         blocks[i].nalloc = 0;
  585.         blocks[i].nused = 0;
  586.         blocks[i].nomem = 0;
  587. #endif
  588.     }
  589.  
  590.     mem_check ();
  591.  
  592.     return (0);
  593. }
  594.  
  595. extern void FAR
  596. mem_term (void)
  597. {
  598.     BLOCK    *p;
  599.     CHUNK    *c, *c1;
  600.     int    i, n;
  601.     long    tt;
  602.     long    avail;
  603.     Ulong    totn;
  604.     Ulong    totbytes;
  605. #ifdef MEM_STATS
  606.     Ulong    totalloc;
  607.     Ulong    totnomem;
  608. #endif
  609.  
  610.     if (!blocks)
  611.         return;
  612.  
  613.     mem_assert ();
  614.  
  615.     totn = totbytes = 0;
  616. #ifdef MEM_STATS
  617.     totalloc = totnomem = 0;
  618. #endif
  619.     LogPrintf ("Memory usage summary:\n\n");
  620.     LogPrintf ("Size  Count     Bytes   nAllocs   nFailed     nUsed\n");
  621.     for (i = 0; i < NBLOCKS; ++i) {
  622.         for (n = 0, p = blocks[i].next[SIZES]; p; p = p->next[SIZES])
  623.             ++n;
  624. #ifdef MEM_STATS
  625.         if (n || blocks[i].nalloc) {
  626.             totalloc += blocks[i].nalloc;
  627.             totnomem += blocks[i].nomem;
  628. #else
  629.         if (n) {
  630. #endif
  631.             totn += n;
  632.             tt = INDEXSIZE(i) * (long)n;
  633.             totbytes += tt;
  634.             LogPrintf ("%4u %6u %9lu", INDEXSIZE(i), n, tt);
  635. #ifdef MEM_STATS
  636.             LogPrintf (" %9lu", blocks[i].nalloc);
  637.             if (blocks[i].nomem || blocks[i].nused)
  638.                 LogPrintf (" %9lu %9d",
  639.                     blocks[i].nomem, blocks[i].nused);
  640. #endif
  641.             LogPrintf ("\n");
  642.         }
  643.     }
  644.     LogPrintf (" tot %6lu %9lu", totn, totbytes);
  645. #ifdef MEM_STATS
  646.     LogPrintf (" %9lu %9lu", totalloc, totnomem);
  647. #endif
  648.     LogPrintf ("\nSize  Count     Bytes   nAllocs   nFailed     nUsed\n");
  649.  
  650.     n = 0;
  651.     avail = 0;
  652.     LogPrintf ("\nChunk    Unused\n");
  653.     for (c1 = chunks; T(c = c1);) {
  654.         ++n;
  655.         LogPrintf ("%5d %9u\n", n, c->avail);
  656.         c1 = c->next;
  657.         avail += c->avail;
  658.         xfree (c);
  659.     }
  660.     LogPrintf ("total %9lu\n\n", avail);
  661.     chunks = 0;
  662.     LogPrintf ("Chunks   %9lu (%u)\n", n*(long)CHUNKSIZE, n);
  663.     LogPrintf ("Unused   %9lu\n", avail);
  664.     LogPrintf ("Alloc'ed %9lu\n", ngrains*GRAIN);
  665.     LogPrintf ("Freed    %9lu\n", totbytes);
  666.     LogPrintf ("Leakage  %9ld\n", ngrains*GRAIN - totbytes);
  667.     LogPrintf ("nReqs    %9ld\n", nReqs);
  668.     LogPrintf ("nProbes  %9ld\n", nProbes);
  669.  
  670.     blocks = xfree (blocks);
  671.     ngrains = 0;
  672. }
  673.  
  674. #undef SIZES
  675. #undef HEADS
  676. #undef TAILS
  677. #undef GRAIN
  678. #undef NBLOCKS
  679. #undef MAXBYTES
  680. #undef CHUNKSIZE
  681. #undef CHUNKMIN
  682. #undef CHUNKPART
  683. #undef MEM_MINLOG
  684. #undef MINBYTES
  685. #undef BYTESINDEX
  686. #undef INDEXSIZE
  687. #undef ROUNDBYTES
  688. #undef PTRINDEX
  689. #undef LISTREMOVE
  690. #undef LISTADD
  691.